package quirk;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
 * This is the main process of the QUIRK program. This class reads
 * the user's commands and handles them accordingly.
 * 
 * @author Andrew Bernard
 */
public class QueryEngine {
  private BufferedReader input;
  private IndexManager mgr = new IndexManager();
  private List queryResults = null;      
  private int queryResultsPointer = 0;
  
  private EngineStats engineStats = new EngineStats();  
  private class EngineStats {
    public int statsCommandCalls = 0;
    public int indexCommandCalls = 0;
    public int queryCommandCalls = 0;
    public int refineCommandCalls = 0;
    public int showCommandCalls = 0;
    public int nextCommandCalls = 0;
    public int retrievalRequests = 0;
    public int falsePositives = 0;
  }
    
  public void run() throws IOException {
    input = new BufferedReader(new InputStreamReader(System.in));
         
    while(true) {
      String command = prompt().toLowerCase();
      try {
        call(command);
      }
      catch (UserInteractionException ex) {
        outln(ex.getMessage());
      }
    }
  }
  
  private String prompt() throws IOException {
    System.out.print("\n??? ");
    return input.readLine();
  }
  
  public void call(String command) 
  throws IOException, UserInteractionException {
    if(command.equals("stats")) {
      engineStats.showCommandCalls++;      
      outln(mgr.getCorpusDetails());
    }
    
    else if(command.equals("index")) {
      engineStats.indexCommandCalls++;
      outln(mgr.getIndexDetails());
    }
    
    else if(command.startsWith("query")) {
      engineStats.queryCommandCalls++;
      
      String query = command.substring(command.indexOf("QUERY")+5); 
      //+5 puts the string index after the command
      
      queryResults = mgr.runQuery(query);      
      displayQueryResultStatus(); 
      queryResultsPointer = 0;
    }
    
    else if(command.startsWith("refine")) {
      engineStats.refineCommandCalls++;
      
      if(queryResults == null)
        throw new UserInteractionException(Constants.ERR_GENERIC);
      else {     
        String refinement = command.substring(command.indexOf("REFINE")+6); 
        //+6 puts the string index after the command
        
        mgr.refineQuery(refinement, queryResults);
        displayQueryResultStatus();
        queryResultsPointer = 0;
      }
    }
    
    else if(command.equals("show")) {
      engineStats.showCommandCalls++; 
      
      if(queryResults == null || queryResults.size() == 0)
        throw new UserInteractionException(Constants.ERR_GENERIC);
      else {
        queryResultsPointer = 0;
        Query.Result result = (Query.Result)queryResults.get(queryResultsPointer++);
        if(result.dataHeader.isOutdated)
          throw new UserInteractionException(Constants.ERR_OUTDATED_INDEX);
        else {
          //waiting on a response from Spencer as to how exactly to implement this command
          outln(result);
        }        
      }      
    }
    
    else if(command.equals("next")) {
      engineStats.nextCommandCalls++;
    }
    
    else if(command.equals("quit")) {
      System.exit(0);
    }
    
    else
      throw new UserInteractionException(Constants.ERR_SYNTAX);
  }
  
  private void displayQueryResultStatus() {
    int matches = queryResults.size();
    String queryResultString = "" + matches;
    if(matches > 0)
      queryResultString += " possible";
    outln(queryResultString + " matches found");
  }
  
  /** This is here because I'm lazy ;) */
  private static void outln(Object obj) {
    System.out.println(obj);
  }
}
